package com.wangzha.business.ctrl;

import com.alibaba.fastjson.JSON;
import com.jfinal.aop.Inject;
import com.jfinal.core.Path;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.upload.UploadFile;
import com.wangzha.business.service.*;
import com.wangzha.common.base.BaseController;
import com.wangzha.common.enums.TaskEnum;
import com.wangzha.common.enums.TaskExecuteTypeEnum;
import com.wangzha.common.enums.TaskStatusEnum;
import com.wangzha.common.model.*;
import com.wangzha.common.oss.OSSProvider;
import com.wangzha.common.vo.Grid;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

import java.io.File;
import java.math.BigInteger;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 任务
 */
@Path("/task")
public class TaskController extends BaseController {

    @Inject
    DeviceService deviceService;

    @Inject
    DeviceGroupService deviceGroupService;

    @Inject
    TaskService taskService;

    @Inject
    UserUploadFileService userUploadFileService;

    @Inject
    Record_recordGroupService record_recordGroupService;

    @Inject
    UserRecordGroupService userRecourdGroupService;

    @Inject
    UserRecordParamService userRecordParamService;

    @Inject
    OSSProvider ossProvider;

    public void index() {
        render("index.html");
    }

    public void add() {
        setAttr("deviceGroupList", deviceGroupService.findByUserCode(getVisitor().getCode()));
        String pageName = getPara("pageName");
        if ("index".equals(pageName)) {
            render("index.html");
        } else if ("publish".equals(pageName)) {
            render("publish.html");
        } else if("syn_file".equals(getPara("pageName"))) {
            setAttr("deviceGroupList", deviceGroupService.findByUserCode(getVisitor().getCode()));
            render("syn_file.html");
        } else if ("stop_task".equals(pageName)) {
            render("stop_task.html");
        } else if ("publish_product".equals(pageName)) {
            render("publish_product.html");
        } else {
            render("add.html");
        }
    }

    public void save() {
        try {
            Integer taskCode = getParaToInt("taskCode");
            Long[] deviceIds = getParaValuesToLong("deviceId");
            Long[] groupIds = getParaValuesToLong("groupId");

            Record record = new Record();
            record.set("user_code", getVisitor().getCode());
            List<DeviceGroup> deviceGroupList = deviceGroupService.findByUserCode(getVisitor().getCode());
            setAttr("deviceGroupList", deviceGroupList);

            List<Device> devices = deviceService.findByUserCodeAndGroupIds(getVisitor().getCode(), new ArrayList<>(Arrays.asList(groupIds)));
            Map<Integer, List<Device>> deviceMapList = devices.stream().collect(Collectors.groupingBy(Device::getGroupId));

            Map<Integer, List<Device>> allDeviceMapList = new HashMap<>();
            allDeviceMapList.putAll(deviceMapList);

            if (ArrayUtils.isNotEmpty(deviceIds)) {
                List<Device> specifiedDevices = deviceService.findByDeviceIds(new ArrayList<>(Arrays.asList(deviceIds)));
                Map<Integer, List<Device>> specifiedDeviceMapList = specifiedDevices.stream().collect(Collectors.groupingBy(Device::getGroupId));
                allDeviceMapList.putAll(specifiedDeviceMapList);
            }

            for (Map.Entry<Integer, List<Device>> entry : allDeviceMapList.entrySet()) {
                for (Device device : entry.getValue()) {
                    Task task = new Task();
                    task.setDeviceId(device.getId().longValue());
                    task.setCreateTime(new Date());
                    task.setState(TaskStatusEnum.READY_TO_RUN.getState());
                    task.setUpdateTime(new Date());
                    task.setUserCode(getVisitor().getCode());
                    task.setType(taskCode);
                    task.setOpMode(getPara("opMode"));
                    task.setRunTime(getInt("runTime"));
                    task.setActiveCode(device.getActivationCode());
                    task.setHome(getParaToInt("home") == null ? 0 : getParaToInt("home"));

                    if (taskCode != null) {
                        if (taskCode == TaskEnum.SCRIPT_TASK.getCode() || taskCode == TaskEnum.SYN_SCRIPT.getCode()) {
                            publisTask(task);
                        } else if (taskCode == TaskEnum.PUBLISH_PRODUCT.getCode()) {
                            publishProduct(task);
                        } else if (taskCode == TaskEnum.STOP_TASK.getCode()) {
                            stopTask(task);
                        }
                    }

                    task.save();
                }
            }
            renderJson(suc());
        } catch(Exception e) {
            e.printStackTrace();
            renderJson(fail());
        }
    }

    public void publisTask(Task task) {
        List taskParams = new ArrayList();
        List<String> groupNames = new ArrayList<>();
        List allTaskList = new ArrayList();
        String groupIdAndRecordIdStr = getPara("recordIds");
        if (StringUtils.isNotBlank(groupIdAndRecordIdStr)) {
            String[] groupIdAndRecordIdArr = groupIdAndRecordIdStr.split(",");
            if (ArrayUtils.isNotEmpty(groupIdAndRecordIdArr)) {
                Map<Long, List<Long>> tempMap = new HashMap(20);
                for (String temp : groupIdAndRecordIdArr) {
                    String[] groupIdAndRecordId = temp.split("\\|");
                    Long groupId = NumberUtils.toLong(groupIdAndRecordId[0]);
                    Long recordId = NumberUtils.toLong(groupIdAndRecordId[1]);
                    List<Long> recordIds = tempMap.get(groupId);
                    if (CollectionUtils.isEmpty(recordIds)) {
                        recordIds = new ArrayList<>();
                    }
                    recordIds.add(recordId);
                    tempMap.put(groupId, recordIds);
                }

                for (Map.Entry<Long, List<Long>> entry : tempMap.entrySet()) {
                    Long groupId = entry.getKey();
                    List<Long> recordIds = entry.getValue();

                    UserRecordGroup userRecordGroup = userRecourdGroupService
                            .findByIdAndUserCode(getVisitor().getCode(), groupId);

                    Map allTaskMap = new HashMap(6);

                    groupNames.add(userRecordGroup.getName());

                    if (CollectionUtils.isNotEmpty(recordIds)) {

                        List<UserRecordParam> userRecordParamList = userRecordParamService.findUserRecordParam(getVisitor().getCode(), userRecordGroup.getId(), recordIds);
                        Map<Long, UserRecordParam> userRecordParamMap = userRecordParamList.stream()
                                .collect(Collectors.toMap(UserRecordParam::getRecordId, Function.identity()));

                        List<UserUploadFile> userUploadFiles = (List<UserUploadFile>) userUploadFileService.findByRecordIds(recordIds);
                        if (CollectionUtils.isNotEmpty(userUploadFiles)) {
                            for (UserUploadFile f : userUploadFiles) {
                                UserRecordParam userRecordParam = userRecordParamMap.get(f.getId());
                                Map map = new HashMap(10) {{
                                    put("identifier", f.getIdentifier());
                                    put("name", f.getName());
                                    put("url", f.getUrl());
                                    put("fileType", f.getType());
                                    if (userRecordParam != null) {
                                        put("runTime", userRecordParam.getRunTime());
                                        put("extraParams", userRecordParam.getExtraParams());
                                        put("pollingInterval", userRecordParam.getPollingInterval());
                                        put("actionInterval", userRecordParam.getActionInterval());
                                    }
                                }};

                                taskParams.add(map);
                            }

                            allTaskMap.put("groupId", userRecordGroup.getId());
                            allTaskMap.put("files", taskParams);
                            allTaskList.add(allTaskMap);
                        }
                    }
                }
            }
        }
        task.setContent(JSON.toJSONString(groupNames));
        task.setTaskParams(JSON.toJSONString(allTaskList));
    }

    /**
     * 停止任务
     *
     * @param task
     */
    public void stopTask(Task task) {
        task.setType(TaskEnum.STOP_TASK.getCode());
    }


    /**
     * 发布作品
     * @param task
     */
    public void publishProduct(Task task) {
        Map<String, Object> map = new HashMap<>();
        map.put("imageUrl", getPara("imageUrl"));
        map.put("videoUrl", getPara("videoUrl"));
        map.put("content", getPara("content"));
        map.put("platform", getPara("platform"));
        task.setStartTime(null);
        task.setType(TaskEnum.PUBLISH_PRODUCT.getCode());
        task.setOpMode(getPara("opMode"));
        task.setRunTime(getParaToInt("runTime"));
        task.setTaskParams(JSON.toJSONString(map));
    }

    public void list() {
        Record record = new Record();
        record.set("user_code", getVisitor().getCode());
        Grid grid = taskService.queryForListEq(getParaToInt("pageNumber", 1),
                getParaToInt("pageSize", 10), record);
        if (grid != null) {
            List<Record> recordList = (List<Record>) grid.getList();
            if (CollectionUtils.isNotEmpty(recordList)) {
                for (Record obj : recordList) {
                    if (obj != null) {
                        obj.set("op_mode", TaskExecuteTypeEnum.getName(obj.getInt("op_mode")));
                        obj.set("state", TaskStatusEnum.getDescByType(obj.getInt("state")));
                    }
                }
            }
            grid.setList(recordList);
        }
        renderJson(grid);
    }



    public void delete() {
        taskService.deleteByIds(getIds());
        renderJson(suc());
    }


    public void edit() {
        UserRecordGroup userRecordGroup = (UserRecordGroup) userRecourdGroupService.findById(getPara(0));
        setAttr("groupId", userRecordGroup.getId());
        render("record_list.html");
    }


    public void updateFieldValue() {

        UserRecordParam userRecordParam = getModel(UserRecordParam.class);
        userRecordParam.setUserCode(getVisitor().getCode());
        String type = getPara("type");

        UserRecordParam tempUserRecordParam = userRecordParamService.findUserRecordParam(userRecordParam.getUserCode(),
                userRecordParam.getGroupId(), userRecordParam.getRecordId());
        if ("run_time".equals(type)) {
            userRecordParam.setRunTime(userRecordParam.getRunTime());
        } else if ("extra_params".equals(type)) {
            userRecordParam.setExtraParams(userRecordParam.getExtraParams());
        }
        boolean flag = false;
        if (tempUserRecordParam == null) {
            flag = userRecordParam.save();
        } else {
            userRecordParam.setId(tempUserRecordParam.getId());
            flag = userRecordParam.update();
        }
        renderJson(suc(flag ? "修改成功" : "修改成功"));
    }


    public void uploadFile() {
        UploadFile uploadFile = getFile();
        if (uploadFile != null) {
            String fileKey = UUID.randomUUID().toString().replaceAll("-", "");
            String url = ossProvider.putObject(uploadFile.getFile(), fileKey);
            File file = new File(uploadFile.getUploadPath() + "/" + uploadFile.getOriginalFileName());
            file.delete();
            if (org.apache.commons.lang.StringUtils.isBlank(url)) {
                renderJson(fail("上传图片失败"));
            }

            if (uploadFile.getFileName().endsWith("jpg") || uploadFile.getFileName().endsWith("png")) {
                renderJson(suc(url));
            }

            if (uploadFile.getFileName().endsWith("mp4")) {
                renderJson(suc(url));
            }
        }
    }

}
